package api

import (
	"math/rand"
	"strconv"
	"time"

	"github.com/EDDYCJY/go-gin-example/models"
	"github.com/EDDYCJY/go-gin-example/pkg/app"
	"github.com/EDDYCJY/go-gin-example/pkg/e"
	"github.com/EDDYCJY/go-gin-example/pkg/setting"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"

	log "github.com/sirupsen/logrus"
)

// 查询所有机器列表
type MachineListReq struct {
	// 页索引
	Page uint32 `form:"page" binding:"gte=1"`
	// 页大小
	PageSize uint32 `form:"page_size" binding:"gte=1"`
	// 国家
	Country string `form:"country"`
	// 城市
	City string `form:"city"`
	// gpu型号
	GpuName string `form:"gpu_name"`
	// gpu数量
	GpuCount uint32 `form:"gpu_count" binding:"gte=0"`
}

func Handle_QueryMachineList(c *gin.Context) {
	appG := app.Gin{C: c}

	var req MachineListReq
	if err := c.ShouldBindQuery(&req); err != nil {
		appG.ResponseError(e.ERROR, "请求参数错误:"+err.Error())
		return
	}

	result, ferror := GetMachineList(&req)
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(result)
	}
}

type MachineItem struct {
	// 机器提交记录id
	ID uint64 `json:"id"`
	// 机器id
	NodeId string `json:"node_id"`
	// 国家
	Country string `json:"country"`
	// 城市
	City string `json:"city"`
	// cpu型号
	CpuName string `json:"cpu_name"`
	// cpu核心数
	CpuCores uint32 `json:"cpu_cores"`
	// cpu频率（MHz）
	CpuFrequency uint32 `json:"cpu_frequency"`
	// 内存大小（MB）
	MemSize uint64 `json:"mem_size"`
	// 磁盘大小（GB）
	DiskSize uint64 `json:"disk_size"`
	// 显卡型号
	GpuName string `json:"gpu_name"`
	// 显存大小（MB）
	GpuMemSize uint64 `json:"gpu_mem_size"`
	// GPU数量
	GpuCount uint32 `json:"gpu_count"`
	// 上行带宽（Mbps）
	UpBandwidth uint32 `json:"up_bandwidth"`
	// 下行带宽（Mbps）
	DownBandwidth uint32 `json:"down_bandwidth"`
	// 机器状态
	Status string `json:"status"`

	// 剩余cpu核心数
	RestCpuCores uint32 `json:"rest_cpu_cores"`
	// 剩余的gpu数量
	RestGpuCount uint32 `json:"rest_gpu_count"`
	// 剩余的内存大小（MB）
	RestMemSize uint64 `json:"rest_mem_size"`
	// 剩余的磁盘大小（GB）
	RestDiskSize uint64 `json:"rest_disk_size"`

	// 上线时间
	OnlineTime models.DbTime `json:"online_time"`
	// 整机日租金
	DayRentCoins float64 `json:"day_rent_coins"`
	// 单卡日租金 实际价格
	OneCardDayRentCoins float64 `json:"one_card_day_rent_coins"`
	//优惠的折扣
	Discount float64 `json:"discount"`
	//单卡优惠价格
	OneCardDayRentCoinsDisCount float64 `json:"one_card_day_rent_coins_dis_count"`
	//整机日租金优惠价格
	DayRentCoinsDisCount float64 `json:"day_rent_coins_dis_count"`
	//系统盘 系统盘：50GB  数据盘：100GB
	SystemDisk uint64 `json:"system_disk"`
	//数据盘100GB
	DataDisk uint64 `json:"data_disk"`
}

type MachineListRsp struct {
	TotalCount  int64         `json:"total"`
	MachineList []MachineItem `json:"machines"`
}

func GetMachineList(req *MachineListReq) (*MachineListRsp, e.FResult) {
	where := make(map[string]interface{})
	if len(req.Country) > 0 {
		where["country"] = req.Country
	}
	if len(req.City) > 0 {
		where["city"] = req.City
	}
	if len(req.GpuName) > 0 {
		where["gpu_name"] = req.GpuName
	}
	if req.GpuCount > 0 {
		where["gpu_count"] = req.GpuCount
	}

	total, ferror := models.GetOnlineSubmitMachineRecordsCount(where)
	if ferror.ErrCode != e.SUCCESS {
		return nil, ferror
	}

	if total == 0 {
		return &MachineListRsp{
			TotalCount:  0,
			MachineList: []MachineItem{},
		}, e.FResult_OK
	}

	infolist, ferror := models.GetOnlineSubmitMachineRecords(req.Page, req.PageSize, where)
	if ferror.ErrCode != e.SUCCESS {
		return nil, e.FResult_ERROR
	}

	var machine_list []MachineItem
	for _, v := range infolist {
		var item MachineItem
		item.ID = v.ID
		item.NodeId = v.NodeId
		item.Country = v.Country
		item.City = v.City
		item.CpuName = v.CpuName
		item.CpuCores = v.CpuCores
		item.CpuFrequency = v.CpuFrequency
		item.MemSize = v.MemSize
		item.DiskSize = v.DiskSize
		item.GpuName = v.GpuName
		item.GpuCount = v.GpuCount
		item.GpuMemSize = v.GpuMemSize
		item.UpBandwidth = v.UpBandwidth
		item.DownBandwidth = v.DownBandwidth
		item.OnlineTime = v.OnlineTime
		// 机器状态
		var t_now = time.Now().UTC()
		if (t_now.After(time.Time(v.RentStartTime)) || t_now.Equal(time.Time(v.RentStartTime))) &&
			t_now.Before(time.Time(v.RentEndTime)) {
			item.Status = "renting" //租用中
		} else {
			item.Status = "ready" //空闲中
		}
		// todo: 根据公式实时计算
		item.DayRentCoins = setting.CloudPlatformSetting.DayRentCoins
		item.OneCardDayRentCoins = setting.CloudPlatformSetting.OneCardDayRentCoins
		//进行计算 优惠价格 9.5折
		item.Discount = 9
		item.OneCardDayRentCoinsDisCount = float64(item.OneCardDayRentCoins*0.9)
		//初始化数据盘 和 系统盘大小
		item.DataDisk = 100
		item.SystemDisk = 50

		if item.Status == "ready" {
			item.RestCpuCores = item.CpuCores
			item.RestMemSize = item.MemSize
			item.RestDiskSize = item.DiskSize
			item.RestGpuCount = item.GpuCount
		} else {
			used_resource := models.GetMachineUsedResource(item.ID)
			if used_resource != nil {
				if used_resource.TaskID == "all" {
					item.RestCpuCores = 0
					item.RestMemSize = 0
					item.RestDiskSize = 0
					item.RestGpuCount = 0
				} else {
					item.RestCpuCores = item.CpuCores - used_resource.CpuCores
					item.RestMemSize = item.MemSize - used_resource.MemSize
					item.RestDiskSize = item.DiskSize - used_resource.DiskSize
					item.RestGpuCount = item.GpuCount - used_resource.GpuCount
				}
			}
		}

		machine_list = append(machine_list, item)
	}

	return &MachineListRsp{
		TotalCount:  total,
		MachineList: machine_list,
	}, e.FResult_OK
}

// 查询所有国家名字
func Hanle_QueryCountryList(c *gin.Context) {
	appG := app.Gin{C: c}

	var country_list = []string{}
	country_list, ferror := models.GetAllContries()
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(country_list)
	}
}

// 查询所有城市名字
func Hanle_QueryCityList(c *gin.Context) {
	appG := app.Gin{C: c}

	var city_list []string
	city_list, ferror := models.GetAllCities()
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(city_list)
	}
}

// 查询所有GPU名字
func Hanle_QueryGpuNameList(c *gin.Context) {
	appG := app.Gin{C: c}

	var gpu_name_list = []string{}
	gpu_name_list, ferror := models.GetAllGpuNames()
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(gpu_name_list)
	}
}

// 查询最大GPU数量
func Hanle_QueryGpuCountMax(c *gin.Context) {
	appG := app.Gin{C: c}

	var max_gpu_count int32 = 0
	max_gpu_count, ferror := models.GetMaxGpuCount()
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(max_gpu_count)
	}
}

// 查询用户的租用订单列表
type RentOrderListReq struct {
	// 页索引
	Page uint32 `form:"page" binding:"gte=1"`
	// 页大小
	PageSize uint32 `form:"page_size" binding:"gte=1"`
}

func Handle_QueryRentOrderList(c *gin.Context) {
	appG := app.Gin{C: c}

	var user_id = uint64(c.GetInt64("user_id"))

	var req RentOrderListReq
	if err := c.ShouldBindQuery(&req); err != nil {
		appG.ResponseError(e.ERROR, "请求参数错误:"+err.Error())
		return
	}

	result, ferror := GetRentOrderList(user_id, &req)
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(result)
	}
}

type tagMachineInfo struct {
	// 机器拥有者的用户id
	OwnerUserId uint64 `json:"owner_user_id"`
	// 机器id
	NodeId string `json:"node_id"`
	// 国家
	Country string `json:"country"`
	// 城市
	City string `json:"city"`
	// cpu型号
	CpuName string `json:"cpu_name"`
	// cpu核心数
	CpuCores uint32 `json:"cpu_cores"`
	// cpu频率（MHz）
	CpuFrequency uint32 `json:"cpu_frequency"`
	// 内存大小（MB）
	MemSize uint64 `json:"mem_size"`
	// 磁盘大小（GB）
	DiskSize uint64 `json:"disk_size"`
	// 显卡型号
	GpuName string `json:"gpu_name"`
	// 显存大小（MB）
	GpuMemSize uint64 `json:"gpu_mem_size"`
	// GPU数量
	GpuCount uint32 `json:"gpu_count"`
	// 上行带宽（Mbps）
	UpBandwidth uint32 `json:"up_bandwidth"`
	// 下行带宽（Mbps）
	DownBandwidth uint32 `json:"down_bandwidth"`
}

type tagVmInfo struct {
	// cpu核心数
	CpuCores uint32 `json:"cpu_cores"`
	// 内存大小（MB）
	MemSize uint64 `json:"mem_size"`
	// 磁盘大小（GB）
	DiskSize uint64 `json:"disk_size"`
	// GPU数量
	GpuCount uint32 `json:"gpu_count"`
}

type RentOrderItem struct {
	// 租用订单id
	ID uint64 `json:"id"`
	// 租用人的用户id
	UseId uint64 `json:"user_id"`
	// 租用状态
	Status string `json:"status"`
	// 租用类型
	RentType uint32 `json:"rent_type"`
	// 虚拟机id
	TaskId string `json:"task_id"`
	// 机器信息
	MachineInfo tagMachineInfo `json:"machine_info"`
	// 虚拟机
	VmInfo tagVmInfo `json:"vm_info"`
	// 租用开始时间
	RentStartTime models.DbTime `json:"rent_start_time"`
	// 租用结束时间
	RentEndTime models.DbTime `json:"rent_end_time"`
	// 已支付的总积分
	TotalPaymentCoins float64 `json:"total_payment_coins"`
}

type RentOrderListRsp struct {
	TotalCount    int64           `json:"total"`
	RentOrderList []RentOrderItem `json:"rent_orders"`
}

func GetRentOrderList(user_id uint64, req *RentOrderListReq) (*RentOrderListRsp, e.FResult) {
	total, ferror := models.GetRentOrdersCountByUserId(user_id)
	if ferror.ErrCode != e.SUCCESS {
		return nil, ferror
	}

	if total == 0 {
		return &RentOrderListRsp{
			TotalCount:    0,
			RentOrderList: []RentOrderItem{},
		}, e.FResult_OK
	}

	infolist, ferror := models.GetRentOrdersByUserId(user_id, req.Page, req.PageSize)
	if ferror.ErrCode != e.SUCCESS {
		return nil, ferror
	}

	var rent_order_list = []RentOrderItem{}
	for _, v := range infolist {
		var item RentOrderItem
		item.ID = v.OrderInfo.ID
		item.UseId = v.OrderInfo.UserId
		item.MachineInfo.OwnerUserId = v.MachineInfo.OwnerUserId
		item.MachineInfo.NodeId = v.MachineInfo.NodeId
		item.MachineInfo.Country = v.MachineInfo.Country
		item.MachineInfo.City = v.MachineInfo.City
		item.MachineInfo.CpuName = v.MachineInfo.CpuName
		item.MachineInfo.CpuCores = v.MachineInfo.CpuCores
		item.MachineInfo.CpuFrequency = v.MachineInfo.CpuFrequency
		item.MachineInfo.MemSize = v.MachineInfo.MemSize
		item.MachineInfo.DiskSize = v.MachineInfo.DiskSize
		item.MachineInfo.GpuName = v.MachineInfo.GpuName
		item.MachineInfo.GpuMemSize = v.MachineInfo.GpuMemSize
		item.MachineInfo.GpuCount = v.MachineInfo.GpuCount
		item.MachineInfo.UpBandwidth = v.MachineInfo.UpBandwidth
		item.MachineInfo.DownBandwidth = v.MachineInfo.DownBandwidth

		item.RentType = v.OrderInfo.RentType
		item.TaskId = v.OrderInfo.TaskId
		item.RentStartTime = v.OrderInfo.RentStartTime
		item.RentEndTime = v.OrderInfo.RentEndTime
		item.TotalPaymentCoins = v.TotalPaymentCoins
		if item.RentType == 2 {
			item.VmInfo.CpuCores = v.VmInfo.CpuCores
			item.VmInfo.MemSize = v.VmInfo.MemSize
			item.VmInfo.DiskSize = v.VmInfo.DiskSize
			item.VmInfo.GpuCount = v.VmInfo.GpuCount
		}

		// 租用状态
		var t_now = time.Now().UTC()
		if (t_now.After(time.Time(v.OrderInfo.RentStartTime)) || t_now.Equal(time.Time(v.OrderInfo.RentStartTime))) &&
			t_now.Before(time.Time(v.OrderInfo.RentEndTime)) {
			item.Status = "renting" //租用中
		} else {
			item.Status = "expire" //已到期
		}

		rent_order_list = append(rent_order_list, item)
	}

	return &RentOrderListRsp{
		TotalCount:    total,
		RentOrderList: rent_order_list,
	}, e.FResult_OK
}

// 查询用户已出租的机器列表
type SubmitMachineListReq struct {
	// 页索引
	Page uint32 `form:"page" binding:"gte=1"`
	// 页大小
	PageSize uint32 `form:"page_size" binding:"gte=1"`
}

func Handle_QuerySubmitMachineList(c *gin.Context) {
	appG := app.Gin{C: c}

	var user_id = uint64(c.GetInt64("user_id"))

	var req SubmitMachineListReq
	if err := c.ShouldBindQuery(&req); err != nil {
		appG.ResponseError(e.ERROR, "请求参数错误:"+err.Error())
		return
	}

	result, ferror := GetSubmitMachineList(user_id, &req)
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(result)
	}
}

type SubmitMachineItem struct {
	// 机器提交记录id
	ID uint64 `json:"id"`
	// 机器拥有者的用户id
	OwnerUserId uint64 `json:"owner_user_id"`
	// 机器id
	NodeId string `json:"node_id"`
	// 国家
	Country string `json:"country"`
	// 城市
	City string `json:"city"`
	// cpu型号
	CpuName string `json:"cpu_name"`
	// cpu核心数
	CpuCores uint32 `json:"cpu_cores"`
	// cpu频率（MHz）
	CpuFrequency uint32 `json:"cpu_frequency"`
	// 内存大小（MB）
	MemSize uint64 `json:"mem_size"`
	// 磁盘大小（GB）
	DiskSize uint64 `json:"disk_size"`
	// 显卡型号
	GpuName string `json:"gpu_name"`
	// 显存大小（MB）
	GpuMemSize uint64 `json:"gpu_mem_size"`
	// GPU数量
	GpuCount uint32 `json:"gpu_count"`
	// 上行带宽（Mbps）
	UpBandwidth uint32 `json:"up_bandwidth"`
	// 下行带宽（Mbps）
	DownBandwidth uint32 `json:"down_bandwidth"`
	// 机器状态
	Status string `json:"status"`
	// 机器提交时间
	SubmitTime models.DbTime `json:"submit_time"`
	// 上线时间
	OnlineTime models.DbTime `json:"online_time"`
	// 收益总积分
	TotalIncomeCoins float64 `json:"total_income_coins"`
}

type SubmitMachineListRsp struct {
	TotalCount        int64               `json:"total"`
	SubmitMachineList []SubmitMachineItem `json:"submit_machines"`
}

func GetSubmitMachineList(user_id uint64, req *SubmitMachineListReq) (*SubmitMachineListRsp, e.FResult) {
	total, ferror := models.GetSubmitMachinesCountByUserId(user_id)
	if ferror.ErrCode != e.SUCCESS {
		return nil, ferror
	}

	if total == 0 {
		return &SubmitMachineListRsp{
			TotalCount:        0,
			SubmitMachineList: []SubmitMachineItem{},
		}, e.FResult_OK
	}

	infolist, ferror := models.GetSubmitMachinesByUserId(user_id, req.Page, req.PageSize)
	if ferror.ErrCode != e.SUCCESS {
		return nil, ferror
	}

	var submit_machine_list []SubmitMachineItem
	for _, v := range infolist {
		var item SubmitMachineItem
		item.ID = v.ID
		item.OwnerUserId = v.OwnerUserId
		item.NodeId = v.NodeId
		item.Country = v.Country
		item.City = v.City
		item.CpuName = v.CpuName
		item.CpuCores = v.CpuCores
		item.CpuFrequency = v.CpuFrequency
		item.MemSize = v.MemSize
		item.DiskSize = v.DiskSize
		item.GpuName = v.GpuName
		item.GpuMemSize = v.GpuMemSize
		item.GpuCount = v.GpuCount
		item.UpBandwidth = v.UpBandwidth
		item.DownBandwidth = v.DownBandwidth
		item.SubmitTime = v.SubmitTime
		item.OnlineTime = v.OnlineTime
		item.TotalIncomeCoins = v.TotalIncomeCoins
		// 租用状态
		var t_now = time.Now().UTC()
		if (t_now.After(time.Time(v.OnlineTime)) || t_now.Equal(time.Time(v.OnlineTime))) &&
			t_now.Before(time.Time(v.OfflineTime)) {
			if (t_now.After(time.Time(v.MaxRentStartTime)) || t_now.After(time.Time(v.MaxRentStartTime))) &&
				t_now.Before(time.Time(v.MaxRentEndTime)) {
				item.Status = "renting" //正在被租用中
			} else {
				item.Status = "ready" //空闲中
			}
		} else {
			item.Status = "offline" //已下线
		}

		submit_machine_list = append(submit_machine_list, item)
	}

	return &SubmitMachineListRsp{
		TotalCount:        int64(total),
		SubmitMachineList: submit_machine_list,
	}, e.FResult_OK
}

// 用户提交要出租的机器信息
type SubmitMachineReq struct {
	// 机器id
	NodeId string `json:"node_id" binding:"required" binding:"gte=1"`
	// 国家
	Country string `json:"country" binding:"required" binding:"gt=0"`
	// 城市
	City string `json:"city" binding:"required" binding:"gt=0"`
	// cpu型号
	CpuName string `json:"cpu_name" binding:"required" binding:"gt=0"`
	// cpu核心数
	CpuCores uint32 `json:"cpu_cores" binding:"required" binding:"gte=1"`
	// cpu频率（MHz）
	CpuFrequency uint32 `json:"cpu_frequency" binding:"required" binding:"gte=1"`
	// 内存大小（MB）
	MemSize uint64 `json:"mem_size" binding:"required" binding:"gte=1"`
	// 磁盘大小（GB）
	DiskSize uint64 `json:"disk_size" binding:"required" binding:"gte=1"`
	// 显卡型号
	GpuName string `json:"gpu_name" binding:"required" binding:"gte=0"`
	// 显存大小（MB）
	GpuMemSize uint64 `json:"gpu_mem_size" binding:"required" binding:"gte=0"`
	// GPU数量
	GpuCount uint32 `json:"gpu_count" binding:"required" binding:"gte=0"`
	// 上行带宽（Mbps）
	UpBandwidth uint32 `json:"up_bandwidth" binding:"required" binding:"gte=1"`
	// 下行带宽（Mbps）
	DownBandwidth uint32 `json:"down_bandwidth" binding:"required" binding:"gte=1"`
}

func Handle_SubmitMachine(c *gin.Context) {
	appG := app.Gin{C: c}

	var user_id = uint64(c.GetInt64("user_id"))
	userInfo, ferror := models.GetUserById(user_id)
	if userInfo == nil {
		appG.ResponseError(e.ERROR, "用户不存在")
		return
	}
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
		return
	}

	white_record, _ := models.GetWhiteUserByUserName(userInfo.UserName)
	if white_record == nil {
		appG.ResponseError(e.ERROR, "您没有提交权限！")
		return
	}

	var req SubmitMachineReq
	if err := c.ShouldBindJSON(&req); err != nil {
		appG.ResponseError(e.ERROR, "请求参数错误:"+err.Error())
		return
	}

	ferror = SubmitMachineWithUser(user_id, &req)
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(nil)
	}
}

func SubmitMachineWithUser(userId uint64, req *SubmitMachineReq) e.FResult {
	var data = models.SubmitMachineRecord{}
	copier.Copy(&data, req)
	data.OwnerUserId = userId
	t_now := time.Now().UTC()
	data.SubmitTime = models.DbTime(t_now)
	data.OnlineTime = models.DbTime(t_now)
	t_offline, _ := time.ParseInLocation("2006-01-02 15:04:05", "6666-01-01 00:00:00", time.UTC)
	data.OfflineTime = models.DbTime(t_offline)

	_, ferror := models.CreateSubmitMachineRecord(&data)
	if ferror.ErrCode != e.SUCCESS {
		return ferror
	}

	return e.FResult_OK
}

// 用户租用机器
type RentMachineReq struct {
	NodeId string `json:"node_id"`
	// 虚拟机
	VmImageName string `json:"image_name"`
	VmOS        string `json:"os"`
	VmBiosMode  string `json:"bios_mode"`
	VmSshPort   uint32 `json:"ssh_port"`
	VmRdpPort   uint32 `json:"rdp_port"`
	VmVncPort   uint32 `json:"vnc_port"`
	VmCpuCores  uint32 `json:"cpu_cores"`
	VmMemSize   uint64 `json:"mem_size"` //内存（MB）
	VmGpuCount  uint32 `json:"gpu_count"`
	VmDiskSize  uint64 `json:"disk_size"` //磁盘（GB）
}

func Handle_RentMachine(c *gin.Context) {
	appG := app.Gin{C: c}

	var user_id = uint64(c.GetInt64("user_id"))

	var req RentMachineReq
	if err := c.ShouldBindJSON(&req); err != nil {
		appG.ResponseError(e.ERROR, "请求参数错误:"+err.Error())
		return
	}

	var submit_machine_record_id, _ = strconv.ParseInt(c.DefaultQuery("record_id", "0"), 10, 64)
	var rent_type, _ = strconv.Atoi(c.DefaultQuery("rent_type", "1"))
	var days, _ = strconv.Atoi(c.DefaultQuery("days", "0"))
	var hours, _ = strconv.Atoi(c.DefaultQuery("hours", "0"))

	if days == 0 && hours == 0 {
		appG.ResponseError(e.ERROR, "days and hours all is 0")
		return
	}

	if rent_type == 2 && req.VmGpuCount == 0 {
		appG.ResponseError(e.ERROR, "'gpu_count' cannot be 0")
		return
	}

	// 设置默认参数
	if rent_type == 2 { //虚拟机
		setDefaultParams(&req)
		log.Debug("req:", req)
	}

	var params models.CreateRentOrderParams
	params.UserID = user_id
	params.RecordID = uint64(submit_machine_record_id)
	params.RentType = uint32(rent_type)
	params.Days = uint32(days)
	params.Hours = uint32(hours)
	params.VmImageName = req.VmImageName
	params.VmOS = req.VmOS
	params.VmBiosMode = req.VmBiosMode
	params.VmSshPort = req.VmSshPort
	params.VmRdpPort = req.VmRdpPort
	params.VmVncPort = req.VmVncPort
	params.VmCpuCores = req.VmCpuCores
	params.VmGpuCount = req.VmGpuCount
	params.VmMemSize = req.VmMemSize
	params.VmDiskSize = req.VmDiskSize

	rsp, ferror := models.CreateRentOrder(&params)
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		if rent_type == 1 {
			appG.ResponseSuccess(nil)
		} else {
			appG.ResponseSuccess(rsp)
		}
	}
}

func setDefaultParams(req *RentMachineReq) {
	if req.VmSshPort == 0 {
		req.VmSshPort = uint32(randomInRange(5900, 65535))
	}

	if req.VmVncPort == 0 {
		req.VmVncPort = uint32(randomInRange(5900, 65535))
	}

	if req.VmCpuCores == 0 {
		req.VmCpuCores = uint32(req.VmGpuCount * 14)
	}

	if req.VmMemSize == 0 {
		req.VmMemSize = uint64(req.VmGpuCount * 64 * 1024)
	}

	if req.VmDiskSize == 0 {
		//100
		//系统盘：50GB  数据盘：100GB
		//参考网址 https://deepbrainchain.github.io/DBC-Wiki/install-update-dbc-node/dbc-client-api/http-api.html#_6-%E5%90%AF%E5%8A%A8%E8%99%9A%E6%8B%9F%E6%9C%BA
		req.VmDiskSize = uint64(req.VmGpuCount * 100)
	}

	if req.VmBiosMode == "" {
		req.VmBiosMode = "legacy"
	}
}

func randomInRange(min, max int) int {
	// 生成随机数
	num := rand.Intn(max-min+1) + min

	return num
}

// 下线已提交的机器
type OfflineSubmitMachineReq struct {
	RecordId uint64 `form:"record_id" binding:"required"`
}

func Handle_offlineSubmitMachine(c *gin.Context) {
	appG := app.Gin{C: c}

	user_id := c.GetInt64("user_id")

	var req OfflineSubmitMachineReq
	if err := c.ShouldBindQuery(&req); err != nil {
		appG.ResponseError(e.ERROR, "请求参数错误:"+err.Error())
		return
	}

	ferror := OfflineMachine(uint64(user_id), req.RecordId)
	if ferror.ErrCode != e.SUCCESS {
		appG.ResponseError(ferror.ErrCode, ferror.ErrMsg)
	} else {
		appG.ResponseSuccess(nil)
	}
}

func OfflineMachine(ownerId uint64, recordId uint64) e.FResult {
	// 查询用户机器
	record, ferror := models.GetSubmitMachineRecordByIdAndOwnerId(recordId, ownerId)
	if ferror.ErrCode != e.SUCCESS {
		return e.FResult{ErrCode: e.ERROR, ErrMsg: "机器不存在"}
	}

	// 当前机器已下线
	var t_now = time.Now().UTC()
	if t_now.Before(time.Time(record.OnlineTime)) ||
		(t_now.After(time.Time(record.OfflineTime)) || t_now.Equal(time.Time(record.OfflineTime))) {
		return e.FResult{ErrCode: e.ERROR, ErrMsg: "机器已下线"}
	}

	// 查询租用状态
	rent_list, ferror := models.GetRentOrdersByRecordId(recordId)
	if ferror.ErrCode != e.SUCCESS {
		return ferror
	}
	if len(rent_list) > 0 {
		return e.FResult{ErrCode: e.ERROR, ErrMsg: "机器正在被租用中，不能下线"}
	}
	// 进行机器下线操作
	ferror = models.OfflineSubmitMachine(recordId)
	if ferror.ErrCode != e.SUCCESS {
		return ferror
	}

	return e.FResult_OK
}

// 查询机器状态
type MachineStatusReq struct {
	NodeId string `form:"node_id" binding:"required"`
}

func Handle_QueryMachineStatus(c *gin.Context) {
	appG := app.Gin{C: c}

	var req MachineStatusReq
	if err := c.ShouldBindQuery(&req); err != nil {
		appG.ResponseError(e.ERROR, "请求参数错误:"+err.Error())
		return
	}

	machineSt := models.GetMachineStatus(req.NodeId)

	appG.ResponseSuccess(machineSt)
}
